package com.gitee.floyd.springme.video.config

import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.gitee.floyd.springme.video.REDIS_CACHE_EXPIRE_DAYS
import com.gitee.floyd.springme.video.REDIS_CACHE_NAME_PLAY_INFO
import com.gitee.floyd.springme.video.REDIS_CACHE_NAME_VIDEO
import com.gitee.floyd.springme.video.REDIS_CACHE_PREFIX
import org.springframework.cache.annotation.EnableCaching
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.cache.CacheKeyPrefix
import org.springframework.data.redis.cache.RedisCacheConfiguration
import org.springframework.data.redis.cache.RedisCacheManager
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer
import org.springframework.data.redis.serializer.RedisSerializationContext
import org.springframework.data.redis.serializer.RedisSerializer
import java.time.Duration

/**
 * @Author gd
 * @Date 2021/9/27 2:51 下午
 */
@Configuration
@EnableCaching
class CacheConfig {

    @Bean
    fun cacheManager(connectionFactory: RedisConnectionFactory): RedisCacheManager {
        val objectMapper = jacksonObjectMapper().apply {
            this.activateDefaultTyping(
                LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.EVERYTHING,
                JsonTypeInfo.As.PROPERTY
            )
        }
        val valueSerializer = GenericJackson2JsonRedisSerializer(objectMapper)
        val shareConfiguration = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofDays(REDIS_CACHE_EXPIRE_DAYS))
            .disableCachingNullValues()
            .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string()))
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer))
            .computePrefixWith { cacheName -> "${REDIS_CACHE_PREFIX}${CacheKeyPrefix.SEPARATOR}${cacheName}${CacheKeyPrefix.SEPARATOR}" }
        return RedisCacheManager
            .builder(connectionFactory)
            .withCacheConfiguration(REDIS_CACHE_NAME_VIDEO, shareConfiguration)
            .withCacheConfiguration(REDIS_CACHE_NAME_PLAY_INFO, shareConfiguration)
            .build()
    }

}
